package com.luxk.db.common;

import java.text.MessageFormat;

import com.luxk.db.errorcode.ErrorCode;

public class ImpactException extends Exception {
	
	static final long serialVersionUID = 0x12345676;
	
	protected ErrorCode errCode = null;
	protected Object args[] = null;
	
	public ImpactException(ErrorCode errCode) {
		super(errCode.getDesc());
		this.errCode = errCode;
	}

	public ImpactException(ErrorCode errCode, Object arg0) {
		super(formatDesc(errCode, arg0));
		this.errCode = errCode;
		this.args = new Object[1];
		this.args[0] = arg0;
	}

	public ImpactException(ErrorCode errCode, Object arg0, Object arg1) {
		super(formatDesc(errCode, arg0, arg1));
		this.errCode = errCode;
		this.args = new Object[2];
		this.args[0] = arg0;
		this.args[1] = arg1;
	}
	
	public ImpactException(ErrorCode errCode, Object arg0, Object arg1, 
			Object arg2) {
		super(formatDesc(errCode, arg0, arg1, arg2));
		this.errCode = errCode;
		this.args = new Object[3];
		this.args[0] = arg0;
		this.args[1] = arg1;
		this.args[2] = arg2;
	}

	public ImpactException(ErrorCode errCode, Throwable t) {
		super(errCode.getDesc(), t);
		this.errCode = errCode;
	}

	public ImpactException(ErrorCode errCode, Throwable t, Object arg0) {
		super(formatDesc(errCode, arg0), t);
		this.errCode = errCode;
		this.args = new Object[1];
		this.args[0] = arg0;
	}

	public ImpactException(ErrorCode errCode,Throwable t, Object arg0,
			Object arg1) {
		super(formatDesc(errCode, arg0, arg1), t);
		this.errCode = errCode;
		this.args = new Object[2];
		this.args[0] = arg0;
		this.args[1] = arg1;
	}

	public ImpactException(ErrorCode errCode, Throwable t, Object arg0, 
			Object arg1, Object arg2) {
		super(formatDesc(errCode, arg0, arg1, arg2), t);
		this.errCode = errCode;
		this.args = new Object[3];
		this.args[0] = arg0;
		this.args[1] = arg1;
		this.args[2] = arg2;
	}

	public ImpactException(ImpactException cause) {
		super(cause.getMessage(), cause);
		this.errCode = cause.getErrorCode();
		this.args = cause.getArgs();
	}
	
	// Errorcode를 사용할 수 없는 경우에만 제한적으로 이 생성자를 사용한다.
	public ImpactException(Throwable t, String msg) {
		super(msg, t);
	}

	public ErrorCode getErrorCode() {
		return this.errCode;
	}
	
	public Object[] getArgs() {
		return this.args;
	}
	
	private static String formatDesc(ErrorCode errCode, Object arg0) {
		return String.format("ERR-%05d %s",  errCode.getCode(), 
				MessageFormat.format(errCode.getDesc(), arg0));
	}

	private static String formatDesc(ErrorCode errCode, Object arg0, Object arg1) {
		return String.format("ERR-%05d %s",  errCode.getCode(), 
				MessageFormat.format(errCode.getDesc(), arg0, arg1));
	}

	private static String formatDesc(ErrorCode errCode, Object arg0, Object arg1,
			Object arg2) {
		return String.format("ERR-%05d %s",  errCode.getCode(), 
				MessageFormat.format(errCode.getDesc(), arg0, arg1, arg2));
	}

	private static String formatDesc(ErrorCode errCode, Object[] args) {
		if(args == null)
			return errCode.getDesc();
		
		String res = null;
		try {
			for(int i = 0; i < args.length; i++) {
				if(args[i] == null)
					args[i] = "null";
			}
			
			res = String.format("ERR-%05d %s", errCode.getCode(), 
					MessageFormat.format(errCode.getDesc(), args));
		} catch(IllegalArgumentException e) {
			StringBuffer buf = new StringBuffer();
			buf.append(String.format("ERR-%05d %s", errCode.getCode(),
					errCode.getDesc()));
			for(int i = 0; i < args.length; i++) {
				buf.append(String.format(" arg #%d=%s", i, args[i]));
			}
			res = buf.toString();
		}
		
		return res;
	}
}
